﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using HtmlAgilityPack;
using RestSharp;

namespace i1 { 
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("请输入搜索关键字: ");
            string keyword = Console.ReadLine();

            var crawler = new WebCrawler();
            crawler.StartCrawling(keyword).Wait();

            Console.WriteLine("已爬取的URL:");
            foreach (var url in crawler.Urls)
            {
                Console.WriteLine(url);
            }

            Console.WriteLine("\n获取到的电话号码:");
            foreach (var phone in crawler.PhoneNumbers)
            {
                Console.WriteLine($"URL: {phone.Url}, Phone: {phone.PhoneNumber}");
            }
        }
    }

    public class WebCrawler
    {
        private const int MaxPhoneNumbers = 100;
        private readonly ConcurrentBag<(string Url, string PhoneNumber)> _phoneNumbers = new ConcurrentBag<(string Url, string PhoneNumber)>();
        private readonly ConcurrentBag<string> _urls = new ConcurrentBag<string>();
        private readonly object _lock = new object();
        private int _phoneCount = 0;

        public IEnumerable<(string Url, string PhoneNumber)> PhoneNumbers => _phoneNumbers;
        public IEnumerable<string> Urls => _urls;

        public async Task StartCrawling(string keyword)
        {
            var searchUrls = await GetSearchUrls(keyword);
            var threads = new List<Thread>();

            foreach (var url in searchUrls)
            {
                var thread = new Thread(() => CrawlWebsite(url));
                threads.Add(thread);
                thread.Start();
            }

            foreach (var thread in threads)
            {
                thread.Join();
            }
        }

    private async Task<IEnumerable<string>> GetSearchUrls(string keyword)
    {
        string searchUrl = $"https://www.google.com/search?q={WebUtility.UrlEncode(keyword)}";
        var client = new RestClient();
        var request = new RestRequest(searchUrl, Method.Get);
        var response = await client.ExecuteAsync(request);

        var htmlDoc = new HtmlDocument();
        htmlDoc.LoadHtml(response.Content);

        var nodes = htmlDoc.DocumentNode.SelectNodes("//a[@href]")
                    ?.Select(node => node.GetAttributeValue("href", string.Empty))
                    .Where(href => href.StartsWith("http"))
                    .Distinct()
                    .ToList() ?? new List<string>();

        return nodes;
    }

        private void CrawlWebsite(string url)
        {
            try
            {
                var client = new RestClient();
                var request = new RestRequest(url, Method.Get);
                var response = client.Execute<RestRequest>(request);

                if (response.IsSuccessful)
                {
                    var htmlDoc = new HtmlDocument();
                    htmlDoc.LoadHtml(response.Content);

                    var phoneNumbers = ExtractPhoneNumbers(htmlDoc.DocumentNode.OuterHtml);
                    lock (_lock)
                    {
                        foreach (var phoneNumber in phoneNumbers)
                        {
                            if (_phoneCount < MaxPhoneNumbers)
                            {
                                _phoneNumbers.Add((url, phoneNumber));
                                _phoneCount++;
                            }
                            else
                            {
                                return;
                            }
                        }

                        _urls.Add(url);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"爬取 {url} 时出错: {ex.Message}");
            }
        }

        private IEnumerable<string> ExtractPhoneNumbers(string htmlContent)
        {
            var phoneRegex = new Regex(@"\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}", RegexOptions.Compiled);
            var matches = phoneRegex.Matches(htmlContent);
            return matches.Cast<Match>().Select(m => m.Value).Distinct();
        }
    }
}